// 把对象数据类型转换成查询字符串
function queryString(obj1) {
    var str = ''
    for (var key in obj1) {
        str += key + '=' + obj1[key] + '&'
    }
    str = str.slice(0, str.length - 1)
    return str
}


// ajax的封装
function ajax(options) {
    // 1. 首先要判断一下是不是一个对象
    if (Object.prototype.toString.call(options) !== '[object Object]') {
        // 提示用户(程序员)要传递一个对象

        // 手动抛出错误(异常)
        // 语法: throw new Error(你要提示的信息)
        // console.log('传递的不是一个对象 请重新传递');
        throw new Error('传递的不是一个对象 请重新传递')
    }
    // 2. 首先要拿到 options 里面的每一个参数
    let { url, method, async, data, headers, datatype, success, error } = options
    // 3.对每一个数据要验证
    // 验证url
    if (!url || typeof url !== 'string') {
        // 手动抛出错误
        throw new Error('你传递的不是一个字符串数据类型')
    }
    // 验证method
    if (!(method === undefined || /^(get|post)$/i.test(method))) {
        // 手动抛出错误
        throw new Error('你传递的不是get或者是post')
    }
    // 验证async
    if (!(async === undefined || typeof async === 'boolean')) {
        // 手动抛出错误
        throw new Error('你传递的不是一个布尔类型的数据')
    }
    // 验证data
    // 传递的数据 可以是没有的 可以是查询字符串 可以是对象
    if (!(data === undefined || typeof data === 'string' || Object.prototype.toString.call(data) === '[object Object]')) {
        // 手动抛出错误
        throw new Error('你传递的数据不是字符串也不是对象 必须要传递一个字符串或者对象数据类型')
    }
    // 验证headers
    if (!(headers === undefined || Object.prototype.toString.call(headers) === '[object Object]')) {
        // 手动抛出错误
        throw new Error('你传递的不是一个对象数据类型 必须要传递一个对象数据类型')
    }
    // 验证datatype
    if (!(datatype === undefined || /^(string|json)$/i.test(datatype))) {
        // 手动抛出错误
        throw new Error('你必须要传递string或者json')
    }
    // 验证success
    if (!(success === undefined || typeof success === 'function')) {
        // 手动抛出错误
        throw new Error('你传递的不是一个函数 我需要一个函数')
    }
    // 验证error
    if (!(error === undefined || typeof error === 'function')) {
        // 手动抛出错误
        throw new Error('你传递的不是一个函数 我需要一个函数')
    }




    // 4. 设计默认值
    let _default = {
        // url的默认值设置
        url: url,
        // 请求方式的默认值
        method: method || 'get',
        // 是否异步的默认值
        // [// async: async || true // 这样是不正确的使用]
        async: typeof async === 'boolean' ? async : true,
        // 空值运算
        // async: async ?? true
        // 参数默认值
        data: data || '',
        // 请求头默认值
        headers: headers || { 'content-type': 'application/x-www-form-urlencoded', ...headers },
        // 是否解析后端数据默认值
        datatype: datatype || 'string',
        // 成功接收后端数据默认值
        success: success || function () { },
        // 失败接收后端数据默认值
        error: error || function () { }


    }
    // 5. 默认值的处理
    if (typeof data === 'object') {
        _default.data = queryString(data)
    }

    // 如果是get请求 并且携带了参数
    if (/^get$/i.test(_default.method) && data) {
        _default.url = _default.url + '?' + _default.data
    }

    // 6. 发送请求
    const xhr = new XMLHttpRequest()

    xhr.open(_default.method, _default.url, _default.async)

    xhr.onload = function () {
        let res = xhr.responseText
        // console.log(res);

        // 判断后端返回的数据是不是json
        if (_default.datatype === 'json') {
            try {
                res = JSON.parse(xhr.responseText)
                _default.success(res)
            } catch (err) {
                _default.error(err)
            }
        } else {
            _default.success(res)
        }
    }

    // 遍历我的headers 拿到对应的键和值

    for (let k in _default.headers) {
        xhr.setRequestHeader(k, _default.headers[k])
    }

    // 发送的时候要考虑是什么请求方式
    // 如果是get请求 直接发送
    // 如果是post 请求有参数的情况下需要在请求体中携带参数

    if (/^get$/i.test(_default.method)) {
        xhr.send()
    } else {
        xhr.send(_default.data)
    }


    console.log(options);
}